package com.kk.gulimall.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kk.common.utils.PageUtils;
import com.kk.common.utils.Query;
import com.kk.gulimall.product.dao.CategoryDao;
import com.kk.gulimall.product.entity.CategoryEntity;
import com.kk.gulimall.product.service.CategoryService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;


@Service("categoryService")
public class CategoryServiceImpl extends ServiceImpl<CategoryDao, CategoryEntity> implements CategoryService {

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<CategoryEntity> page = this.page (
                new Query<CategoryEntity> ( ).getPage (params),
                new QueryWrapper<CategoryEntity> ( )
        );

        return new PageUtils (page);
    }

    @Override
    public List<CategoryEntity> listWithTree() {
        // return listWithTree2();
        List<CategoryEntity> entities = baseMapper.selectList (null);

        // 各个方法内的名字声明还不能一样
        List<CategoryEntity> resultCa = entities.stream ().filter (
                // 过滤非根层下的数据
                categoryEntity -> categoryEntity.getParentCid ()==0
        ).map (
                // 子菜单查询并映射
                menu -> {
                    // 通过 工具方法 获取所有分类 映射到 root 顶层菜单
                    menu.setChildren (getChildrens (menu, entities));
                    return menu;
                }
        ).sorted (
                // 所有返回的 子菜单排序（下面没有高亮，说明编码默认已经是这样排序）
                (menu1,menu2) -> (menu1.getSort ()==null?0:menu1.getSort ())
                        -(menu2.getSort ()==null?0:menu2.getSort ())
        ).collect(
                // 最后返回的类型
                Collectors.toList());

        return resultCa;
    }

    @Override
    public void removeMenuByIds(List<Long> asList) {
        // 检查是否其他地方引用


        baseMapper.deleteBatchIds (asList);
    }

    /**
     * 工具方法：递归查找所有菜单的子菜单(将所有分类过滤分配级别)
     *
     * @param root 父菜单
     * @param all  所有子菜单
     * @return
     */
    private List<CategoryEntity> getChildrens(CategoryEntity root, List<CategoryEntity> all) {
        List<CategoryEntity> children = all.stream ().filter (
                categoryEntity -> categoryEntity.getParentCid ()==root.getCatId ()
        ).map (
                menu ->{
                    menu.setChildren (getChildrens (menu,all));
                    return menu;
                }
        ).sorted (
                // 所有返回的 子菜单排序（下面没有高亮，说明编码默认已经是这样排序）
                (menu1,menu2) -> (menu1.getSort ()==null?0:menu1.getSort ())
                        -(menu2.getSort ()==null?0:menu2.getSort ())
        ).collect(Collectors.toList());

        return children;
    }


    // 案例使用 stream 并行流，虽然说处理这个tree可以说调度多个CPU去分解然后再合并数据会比较快
    // 但是从整个系统的角度来说，CPU不仅仅只有处理这一块数据，然后这一块数据占据多个CPU那么性能相对系统则是未知
    // 而相对这个操作会比较快，这里自己采用循环解决，尽可能介绍重复数据的遍历
    public List<CategoryEntity> listWithTree2() {
        // 查询所有
        List<CategoryEntity> list = baseMapper.selectList (null);

        // 组装树（递归层级拼装）
        // 1、通过遍历查找最底层已经组合出 为0的顶层并从集合中剔除
        int levelNum = 1;
        Map<Long, CategoryEntity> zeroCategoryMap = new ConcurrentHashMap<> ( );// key为id
        Map<Integer, CategoryEntity> resultCategoryMap = new HashMap<> ( );// key为排序值
        for (int i = 0; i < list.size ( ); i++) {

            CategoryEntity categoryEntity = list.get (i);

            if (categoryEntity.getCatLevel ( ) > levelNum) {
                levelNum = categoryEntity.getCatLevel ( );
            }

            if (categoryEntity.getParentCid ( ) == 0) {
                zeroCategoryMap.put (categoryEntity.getCatId ( ), categoryEntity);
                list.remove (categoryEntity);
            }

            // 排序放在最后 转List时候做
        }

        int levelTemp = 2;
        Map<Long, CategoryEntity> categoryMapTemp = new ConcurrentHashMap<> ( );//  key为 父id
        while (levelNum > levelTemp) {
            for (int i = 0; i < list.size ( ); i++) {
                CategoryEntity categoryEntity = list.get (i);
                if (categoryEntity.getCatLevel ( ) == levelTemp) {
                    categoryMapTemp.put (categoryEntity.getParentCid ( ), categoryEntity);
                    list.remove (categoryEntity);
                }
            }

            List<CategoryEntity> chirendList = new ArrayList<> ( );
            for (Long pid : zeroCategoryMap.keySet ( )) {
                for (Long id : categoryMapTemp.keySet ( )) {
                    if (pid == id) {
                        chirendList.add (categoryMapTemp.get (id));
                    }
                }
                CategoryEntity categoryEntity = zeroCategoryMap.get (pid);
                categoryEntity.setChildren (chirendList);
                resultCategoryMap.put (categoryEntity.getSort (),categoryEntity);
            }

            // 排序，重置 mapTemp
            zeroCategoryMap = new HashMap<> (categoryMapTemp);
            categoryMapTemp = new HashMap<> ( );
            levelTemp += 1;
        }

        list = new ArrayList<> (resultCategoryMap.values ());
        return list;
    }

}
